⚡️ Speed up function _parse_latex_cell_styles by 23%
#314
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
📄 23% (0.23x) speedup for
_parse_latex_cell_stylesinpandas/io/formats/style_render.py⏱️ Runtime :
1.25 milliseconds→1.02 milliseconds(best of106runs)📝 Explanation and details
The optimized code achieves a 23% speedup through several key performance improvements:
What optimizations were applied:
Avoided repeated list slicing: Replaced
latex_styles[::-1]withreversed(latex_styles)to eliminate creating a reversed copy of the list, saving memory allocation overhead.Lazy formatter dictionary initialization: Instead of creating the formatter dictionary on every loop iteration (678 times in profiling), it's now created only once when needed and reused, dramatically reducing dictionary construction overhead.
Pre-compiled regex patterns: Moved regex compilation outside the inner
colorfunction to avoid recompiling patterns on each CSS color conversion call.Improved string formatting: Used
.format()method with template strings instead of f-strings in the loop, providing more efficient string construction for complex formatting operations.Micro-optimizations: Changed
extend([latex_style])toappend(latex_style)to avoid unnecessary list wrapper creation, and optimized string conversion patterns.Why these optimizations lead to speedup:
reversed()is more memory-efficient than slice notation for iteration, especially with larger style lists.Performance characteristics based on test results:
The optimization is most beneficial for workloads with multiple LaTeX styles or frequent CSS-to-LaTeX conversions, making it valuable for pandas styling operations that process many styled cells.
✅ Correctness verification report:
⚙️ Existing Unit Tests and Runtime
io/formats/style/test_to_latex.py::test_parse_latex_cell_styles_basicio/formats/style/test_to_latex.py::test_parse_latex_cell_styles_braces🌀 Generated Regression Tests and Runtime
from future import annotations
import re
from collections.abc import Callable
from functools import partial
from typing import Union
imports
import pytest
from pandas.io.formats.style_render import _parse_latex_cell_styles
CSSPair = tuple[str, Union[str, float]]
CSSList = list[CSSPair]
from pandas.io.formats.style_render import _parse_latex_cell_styles
unit tests
--------------------------
Basic Test Cases
--------------------------
def test_empty_styles_returns_display_value():
# No styles, should return display_value unchanged
codeflash_output = _parse_latex_cell_styles([], "foo") # 768ns -> 690ns (11.3% faster)
def test_single_simple_style():
# Single style, no wrap/flag
codeflash_output = _parse_latex_cell_styles([("textbf", "")], "bar") # 2.78μs -> 1.81μs (54.2% faster)
def test_single_style_with_option():
# Single style with option
codeflash_output = _parse_latex_cell_styles([("color", "{red}")], "baz") # 2.63μs -> 1.82μs (45.1% faster)
def test_multiple_simple_styles():
# Multiple styles, no wrap/flag
styles = [("textbf", ""), ("color", "{red}")]
# Should nest: \textbf{\color{red} foo}
codeflash_output = _parse_latex_cell_styles(styles, "foo") # 3.92μs -> 2.31μs (70.2% faster)
def test_multiple_styles_with_options():
# Multiple styles with options
styles = [("color", "{red}"), ("cellcolor", "[HTML]{FFEEAA}")]
# Should nest: \color{red}{\cellcolor[HTML]{FFEEAA} foo}
codeflash_output = _parse_latex_cell_styles(styles, "foo") # 4.04μs -> 2.50μs (61.7% faster)
def test_single_style_with_rwrap():
# Single style with --rwrap
codeflash_output = _parse_latex_cell_styles([("color", "{red}--rwrap")], "foo") # 4.72μs -> 5.68μs (17.0% slower)
def test_single_style_with_wrap():
# Single style with --wrap
codeflash_output = _parse_latex_cell_styles([("color", "{red}--wrap")], "foo") # 4.09μs -> 4.80μs (14.7% slower)
def test_single_style_with_nowrap():
# Single style with --nowrap
codeflash_output = _parse_latex_cell_styles([("color", "{red}--nowrap")], "foo") # 3.77μs -> 4.48μs (15.8% slower)
def test_single_style_with_lwrap():
# Single style with --lwrap
codeflash_output = _parse_latex_cell_styles([("color", "{red}--lwrap")], "foo") # 4.18μs -> 4.64μs (9.86% slower)
def test_single_style_with_dwrap():
# Single style with --dwrap
codeflash_output = _parse_latex_cell_styles([("color", "{red}--dwrap")], "foo") # 4.21μs -> 4.86μs (13.3% slower)
def test_multiple_styles_with_wrap_flags():
# Multiple styles with different wrap flags
styles = [("color", "{red}--wrap"), ("cellcolor", "[HTML]{FFEEAA}--rwrap")]
# Should nest: {\color{red} \cellcolor[HTML]{FFEEAA}{foo}}
codeflash_output = _parse_latex_cell_styles(styles, "foo") # 6.86μs -> 7.41μs (7.39% slower)
def test_preserves_whitespace_in_display_value():
# Display value with whitespace should be preserved
codeflash_output = _parse_latex_cell_styles([("textbf", "")], " foo bar ") # 2.69μs -> 1.87μs (43.5% faster)
--------------------------
Edge Test Cases
--------------------------
def test_style_with_comment_and_flag():
# Option contains css comment and flag
codeflash_output = _parse_latex_cell_styles([("color", "red /* --wrap */ --wrap")], "foo") # 4.78μs -> 5.50μs (13.0% slower)
def test_style_with_float_option():
# Option is a float
codeflash_output = _parse_latex_cell_styles([("foo", 3.14)], "bar") # 5.50μs -> 4.12μs (33.2% faster)
def test_style_with_flag_in_middle_of_option():
# --wrap in the middle of the option string
codeflash_output = _parse_latex_cell_styles([("color", "red--wrapfoo")], "baz") # 4.27μs -> 5.21μs (17.9% slower)
def test_style_with_flag_and_extra_spaces():
# Spaces around flag and option
codeflash_output = _parse_latex_cell_styles([("color", " red --wrap ")], "baz") # 4.33μs -> 5.02μs (13.7% slower)
def test_style_with_empty_option_and_flag():
# Empty option but with flag
codeflash_output = _parse_latex_cell_styles([("textbf", "--wrap")], "baz") # 3.76μs -> 4.51μs (16.7% slower)
def test_multiple_flags_only_first_applies():
# Only the first flag in the recognized order is used
codeflash_output = _parse_latex_cell_styles([("color", "{red}--wrap--rwrap--nowrap")], "foo") # 4.25μs -> 4.69μs (9.33% slower)
def test_flag_case_sensitivity():
# Flags are case sensitive, so "--WRAP" should not be recognized
codeflash_output = _parse_latex_cell_styles([("color", "{red}--WRAP")], "foo") # 2.70μs -> 1.95μs (38.7% faster)
def test_non_str_option_is_converted():
# Option is a number, should be converted to string
codeflash_output = _parse_latex_cell_styles([("foo", 42)], "bar") # 2.94μs -> 1.99μs (47.7% faster)
def test_option_with_multiple_flags_and_comment():
# Option with multiple flags and a comment
codeflash_output = _parse_latex_cell_styles([("color", "red /* --wrap */ --wrap--rwrap")], "foo") # 4.94μs -> 5.88μs (16.0% slower)
def test_empty_display_value():
# Empty display_value should still wrap correctly
codeflash_output = _parse_latex_cell_styles([("color", "{red}--wrap")], "") # 4.37μs -> 4.65μs (6.04% slower)
def test_style_with_non_ascii_characters():
# Option contains non-ascii characters
codeflash_output = _parse_latex_cell_styles([("foo", "ßü--wrap")], "bar") # 5.00μs -> 5.51μs (9.10% slower)
def test_style_with_special_latex_characters():
# Option contains LaTeX special chars
codeflash_output = _parse_latex_cell_styles([("foo", r"\alpha--wrap")], "bar") # 4.13μs -> 4.75μs (12.9% slower)
--------------------------
Large Scale Test Cases
--------------------------
def test_large_number_of_styles():
# Apply 100 styles, should nest 100 times
styles = [(f"cmd{i}", f"opt{i}") for i in range(100)]
codeflash_output = _parse_latex_cell_styles(styles, "foo"); result = codeflash_output # 96.6μs -> 27.4μs (253% faster)
# The result should have 100 opening commands, each nesting the next
expected = "foo"
for i in reversed(range(100)):
expected = f"\cmd{i}opt{i} {expected}"
def test_large_number_of_styles_with_wrap_flags():
# Apply 50 styles, each with --wrap
styles = [(f"cmd{i}", f"opt{i}--wrap") for i in range(50)]
codeflash_output = _parse_latex_cell_styles(styles, "foo"); result = codeflash_output # 61.3μs -> 56.4μs (8.73% faster)
# Should nest 50 times with wrap, i.e. {...{...{foo}...}}
expected = "foo"
for i in reversed(range(50)):
expected = f"{{\cmd{i} opt{i} {expected}}}"
def test_large_number_of_styles_mixed_flags():
# Mix --wrap and --rwrap and no flag
styles = []
for i in range(10):
if i % 3 == 0:
styles.append((f"cmd{i}", f"opt{i}--wrap"))
elif i % 3 == 1:
styles.append((f"cmd{i}", f"opt{i}--rwrap"))
else:
styles.append((f"cmd{i}", f"opt{i}"))
codeflash_output = _parse_latex_cell_styles(styles, "foo"); result = codeflash_output # 13.9μs -> 13.1μs (6.52% faster)
# Build expected result step by step
expected = "foo"
for i in reversed(range(10)):
opt = f"opt{i}"
if i % 3 == 0:
expected = f"{{\cmd{i} {opt} {expected}}}"
elif i % 3 == 1:
expected = f"\cmd{i}{opt}{{{expected}}}"
else:
expected = f"\cmd{i}{opt} {expected}"
def test_long_display_value():
# Long display_value, should be preserved
long_val = "x" * 500
codeflash_output = _parse_latex_cell_styles([("foo", "bar")], long_val) # 2.92μs -> 1.87μs (56.0% faster)
def test_large_styles_and_long_display_value():
# Combine many styles and a long display_value
long_val = "y" * 200
styles = [(f"cmd{i}", f"opt{i}") for i in range(20)]
codeflash_output = _parse_latex_cell_styles(styles, long_val); result = codeflash_output # 16.3μs -> 6.86μs (138% faster)
expected = long_val
for i in reversed(range(20)):
expected = f"\cmd{i}opt{i} {expected}"
--------------------------
Tests for convert_css=True and CSS conversion
--------------------------
def test_convert_css_font_weight_bold():
# Should convert font-weight:bold to bfseries
css = [("font-weight", "bold")]
codeflash_output = _parse_latex_cell_styles(css, "foo", convert_css=True) # 6.47μs -> 7.26μs (10.9% slower)
def test_convert_css_font_style_italic():
# Should convert font-style:italic to itshape
css = [("font-style", "italic")]
codeflash_output = _parse_latex_cell_styles(css, "foo", convert_css=True) # 5.97μs -> 6.84μs (12.7% slower)
def test_convert_css_color_named():
# Should convert color:red to \color{red} foo
css = [("color", "red")]
codeflash_output = _parse_latex_cell_styles(css, "foo", convert_css=True) # 6.81μs -> 7.90μs (13.7% slower)
def test_convert_css_color_hex6():
# Should convert color:#abcdef to \color[HTML]{ABCDEF} foo
css = [("color", "#abcdef")]
codeflash_output = _parse_latex_cell_styles(css, "foo", convert_css=True) # 7.26μs -> 8.18μs (11.2% slower)
def test_convert_css_color_hex3():
# Should convert color:#abc to \color[HTML]{AABBCC} foo
css = [("color", "#abc")]
codeflash_output = _parse_latex_cell_styles(css, "foo", convert_css=True) # 7.88μs -> 8.91μs (11.5% slower)
def test_convert_css_color_rgb():
# Should convert color:rgb(128,255,0) to \color[rgb]{0.502, 1.000, 0.000} foo
css = [("color", "rgb(128, 255, 0)")]
codeflash_output = _parse_latex_cell_styles(css, "foo", convert_css=True) # 17.4μs -> 16.3μs (6.60% faster)
def test_convert_css_color_rgba():
# Should convert color:rgba(128,255,0,0.5) to \color[rgb]{0.502, 1.000, 0.000} foo (ignoring alpha)
css = [("color", "rgba(128, 255, 0, 0.5)")]
codeflash_output = _parse_latex_cell_styles(css, "foo", convert_css=True) # 15.8μs -> 15.5μs (2.17% faster)
def test_convert_css_background_color_hex6():
# Should convert background-color:#123456 to \cellcolor[HTML]{123456--lwrap} foo
css = [("background-color", "#123456")]
# --lwrap is always added for background-color
codeflash_output = _parse_latex_cell_styles(css, "foo", convert_css=True) # 9.58μs -> 12.1μs (20.8% slower)
def test_convert_css_with_wrap_flag():
# Should convert font-weight:bold--wrap to \bfseries foo, but with wrap
css = [("font-weight", "bold--wrap")]
codeflash_output = _parse_latex_cell_styles(css, "foo", convert_css=True) # 7.81μs -> 10.5μs (25.3% slower)
def test_convert_css_multiple_styles():
# Multiple CSS styles, should nest accordingly
css = [("font-weight", "bold"), ("color", "red")]
# Should be: \bfseries{\color{red} foo}
codeflash_output = _parse_latex_cell_styles(css, "foo", convert_css=True) # 8.98μs -> 9.05μs (0.861% slower)
def test_convert_css_with_latex_passthrough():
# If value has --latex, should not convert, but drop --latex
css = [("color", "{red}--latex")]
codeflash_output = _parse_latex_cell_styles(css, "foo", convert_css=True) # 9.15μs -> 9.22μs (0.705% slower)
def test_convert_css_unknown_attribute_is_ignored():
# Unknown CSS attribute is ignored
css = [("unknown", "value")]
codeflash_output = _parse_latex_cell_styles(css, "foo", convert_css=True) # 2.97μs -> 4.67μs (36.4% slower)
def test_convert_css_large_number_of_styles():
# Large number of CSS styles, all font-weight:bold
css = [("font-weight", "bold")] * 100
codeflash_output = _parse_latex_cell_styles(css, "foo", convert_css=True); result = codeflash_output # 127μs -> 60.0μs (112% faster)
expected = "foo"
for _ in range(100):
expected = r"\bfseries " + expected
codeflash_output is used to check that the output of the original code is the same as that of the optimized code.
#------------------------------------------------
from future import annotations
import re
from collections.abc import Callable
from functools import partial
from typing import Union
imports
import pytest
from pandas.io.formats.style_render import _parse_latex_cell_styles
CSSPair = tuple[str, Union[str, float]]
CSSList = list[CSSPair]
from pandas.io.formats.style_render import _parse_latex_cell_styles
unit tests
--------------------- BASIC TEST CASES ---------------------
def test_single_basic_command():
# Single command, no special options
codeflash_output = _parse_latex_cell_styles([("textbf", "")], "val"); result = codeflash_output # 2.96μs -> 1.92μs (54.4% faster)
def test_single_command_with_option():
# Single command, with option string
codeflash_output = _parse_latex_cell_styles([("textcolor", "red")], "val"); result = codeflash_output # 2.67μs -> 1.80μs (48.1% faster)
def test_multiple_commands_order():
# Multiple commands: nesting order should be correct (most recent is innermost)
codeflash_output = _parse_latex_cell_styles([("c1", "o1"), ("c2", "o2")], "val"); result = codeflash_output # 3.94μs -> 2.30μs (71.2% faster)
def test_wrap_flag_basic():
# Command with --wrap flag
codeflash_output = _parse_latex_cell_styles([("textbf", "red--wrap")], "val"); result = codeflash_output # 4.50μs -> 5.69μs (20.9% slower)
def test_rwrap_flag_basic():
# Command with --rwrap flag
codeflash_output = _parse_latex_cell_styles([("textbf", "red--rwrap")], "val"); result = codeflash_output # 4.27μs -> 4.94μs (13.5% slower)
def test_nowrap_flag_basic():
# Command with --nowrap flag
codeflash_output = _parse_latex_cell_styles([("textbf", "red--nowrap")], "val"); result = codeflash_output # 3.87μs -> 4.57μs (15.2% slower)
def test_lwrap_flag_basic():
# Command with --lwrap flag
codeflash_output = _parse_latex_cell_styles([("textbf", "red--lwrap")], "val"); result = codeflash_output # 4.01μs -> 4.79μs (16.2% slower)
def test_dwrap_flag_basic():
# Command with --dwrap flag
codeflash_output = _parse_latex_cell_styles([("textbf", "red--dwrap")], "val"); result = codeflash_output # 4.28μs -> 4.84μs (11.5% slower)
def test_multiple_flags_nesting():
# Multiple commands, one with --wrap, one without
codeflash_output = _parse_latex_cell_styles([("c1", "o1--wrap"), ("c2", "o2")], "val"); result = codeflash_output # 5.43μs -> 5.38μs (0.892% faster)
def test_strip_options_comments():
# Option string with CSS-style comments
codeflash_output = _parse_latex_cell_styles([("textbf", "red /* --wrap */")], "val"); result = codeflash_output # 4.38μs -> 5.10μs (14.2% slower)
--------------------- EDGE TEST CASES ---------------------
def test_empty_styles_list():
# Empty styles list should return display_value unchanged
codeflash_output = _parse_latex_cell_styles([], "val"); result = codeflash_output # 767ns -> 574ns (33.6% faster)
def test_empty_display_value():
# Empty display_value should still wrap correctly
codeflash_output = _parse_latex_cell_styles([("textbf", "")], ""); result = codeflash_output # 2.71μs -> 1.77μs (52.8% faster)
def test_command_with_empty_option_and_flag():
# Option is just a flag, no value
codeflash_output = _parse_latex_cell_styles([("textbf", "--wrap")], "val"); result = codeflash_output # 4.04μs -> 4.88μs (17.2% slower)
def test_command_with_numeric_option():
# Option is a number
codeflash_output = _parse_latex_cell_styles([("fontsize", 12)], "val"); result = codeflash_output # 3.01μs -> 1.91μs (57.2% faster)
def test_command_with_float_option_and_flag():
# Option is a float and a flag
codeflash_output = _parse_latex_cell_styles([("fontsize", "12.5--rwrap")], "val"); result = codeflash_output # 4.50μs -> 5.24μs (14.0% slower)
def test_command_with_multiple_flags_in_option():
# Option contains multiple flags; should only use first
codeflash_output = _parse_latex_cell_styles([("textbf", "red--wrap--rwrap")], "val"); result = codeflash_output # 4.17μs -> 4.77μs (12.7% slower)
def test_command_with_flag_and_comment():
# Option contains flag and CSS comment
codeflash_output = _parse_latex_cell_styles([("textbf", "red /* --wrap */")], "val"); result = codeflash_output # 4.68μs -> 5.11μs (8.35% slower)
def test_convert_css_font_weight():
# CSS conversion for font-weight
codeflash_output = _parse_latex_cell_styles([("font-weight", "bold")], "val", convert_css=True); result = codeflash_output # 6.31μs -> 7.11μs (11.2% slower)
def test_convert_css_font_style_italic():
# CSS conversion for font-style italic
codeflash_output = _parse_latex_cell_styles([("font-style", "italic")], "val", convert_css=True); result = codeflash_output # 5.95μs -> 6.68μs (10.9% slower)
def test_convert_css_color_named():
# CSS conversion for color named
codeflash_output = _parse_latex_cell_styles([("color", "red")], "val", convert_css=True); result = codeflash_output # 7.31μs -> 8.18μs (10.6% slower)
def test_convert_css_color_hex():
# CSS conversion for color hex
codeflash_output = _parse_latex_cell_styles([("color", "#ff23ee")], "val", convert_css=True); result = codeflash_output # 7.62μs -> 8.33μs (8.57% slower)
def test_convert_css_color_hex_short():
# CSS conversion for short hex
codeflash_output = _parse_latex_cell_styles([("color", "#f0e")], "val", convert_css=True); result = codeflash_output # 8.09μs -> 8.74μs (7.50% slower)
def test_convert_css_color_rgb():
# CSS conversion for rgb
codeflash_output = _parse_latex_cell_styles([("color", "rgb(128, 255, 0)")], "val", convert_css=True); result = codeflash_output # 16.9μs -> 15.6μs (8.87% faster)
def test_convert_css_color_rgba():
# CSS conversion for rgba
codeflash_output = _parse_latex_cell_styles([("color", "rgba(128, 255, 0, 0.5)")], "val", convert_css=True); result = codeflash_output # 15.6μs -> 15.4μs (0.738% faster)
def test_convert_css_background_color_named():
# CSS conversion for background-color named
codeflash_output = _parse_latex_cell_styles([("background-color", "red")], "val", convert_css=True); result = codeflash_output # 8.72μs -> 11.5μs (24.1% slower)
def test_convert_css_background_color_hex():
# CSS conversion for background-color hex
codeflash_output = _parse_latex_cell_styles([("background-color", "#ff23ee")], "val", convert_css=True); result = codeflash_output # 9.27μs -> 11.5μs (19.3% slower)
def test_convert_css_with_flag_in_value():
# CSS conversion with flag in value
codeflash_output = _parse_latex_cell_styles([("font-weight", "bold--wrap")], "val", convert_css=True); result = codeflash_output # 7.86μs -> 10.1μs (21.9% slower)
def test_convert_css_with_latex_tag():
# CSS conversion with --latex tag should skip conversion, drop --latex
codeflash_output = _parse_latex_cell_styles([("font-weight", "bold--latex")], "val", convert_css=True); result = codeflash_output # 6.28μs -> 7.03μs (10.7% slower)
def test_convert_css_multiple_styles_nesting():
# Multiple CSS styles, converted and nested
styles = [("font-weight", "bold"), ("color", "red")]
codeflash_output = _parse_latex_cell_styles(styles, "val", convert_css=True); result = codeflash_output # 9.14μs -> 9.22μs (0.846% slower)
def test_convert_css_multiple_styles_with_flags():
# Multiple CSS styles, some with flags
styles = [("font-weight", "bold--wrap"), ("color", "red--rwrap")]
codeflash_output = _parse_latex_cell_styles(styles, "val", convert_css=True); result = codeflash_output # 13.4μs -> 15.9μs (16.1% slower)
def test_convert_css_background_color_with_flag():
# background-color with --wrap flag
codeflash_output = _parse_latex_cell_styles([("background-color", "red--wrap")], "val", convert_css=True); result = codeflash_output # 8.68μs -> 11.1μs (22.2% slower)
def test_convert_css_background_color_with_lwrap_flag():
# background-color with --lwrap flag
codeflash_output = _parse_latex_cell_styles([("background-color", "red--lwrap")], "val", convert_css=True); result = codeflash_output # 8.85μs -> 10.9μs (18.7% slower)
def test_convert_css_font_style_oblique():
# CSS conversion for font-style oblique
codeflash_output = _parse_latex_cell_styles([("font-style", "oblique")], "val", convert_css=True); result = codeflash_output # 6.01μs -> 6.85μs (12.3% slower)
def test_convert_css_font_style_unknown():
# Unknown font-style should not convert
codeflash_output = _parse_latex_cell_styles([("font-style", "normal")], "val", convert_css=True); result = codeflash_output # 3.90μs -> 5.61μs (30.4% slower)
def test_convert_css_font_weight_unknown():
# Unknown font-weight should not convert
codeflash_output = _parse_latex_cell_styles([("font-weight", "normal")], "val", convert_css=True); result = codeflash_output # 4.00μs -> 5.62μs (28.7% slower)
def test_convert_css_with_nonconvertible_style():
# Non-convertible CSS attribute should not affect output
codeflash_output = _parse_latex_cell_styles([("border", "1px solid black")], "val", convert_css=True); result = codeflash_output # 3.08μs -> 4.69μs (34.5% slower)
--------------------- LARGE SCALE TEST CASES ---------------------
def test_large_number_of_styles_nesting():
# Large number of styles, test nesting and performance
styles = [(f"cmd{i}", f"opt{i}") for i in range(50)]
codeflash_output = _parse_latex_cell_styles(styles, "val"); result = codeflash_output # 44.9μs -> 14.5μs (210% faster)
# Should nest as: \cmd0opt0{\cmd1opt1{...{\cmd49opt49 val}...}}
expected = "val"
for i in reversed(range(50)):
expected = f"\cmd{i}opt{i}{{{expected}}}"
def test_large_number_of_styles_with_flags():
# Large number of styles, all with --wrap flag
styles = [(f"cmd{i}", f"opt{i}--wrap") for i in range(50)]
codeflash_output = _parse_latex_cell_styles(styles, "val"); result = codeflash_output # 62.0μs -> 57.7μs (7.36% faster)
# Should nest as: {\cmd0opt0 {\cmd1opt1 {...{\cmd49opt49 val}...}}}
expected = "val"
for i in reversed(range(50)):
expected = f"{{\cmd{i}opt{i} {expected}}}"
def test_large_scale_css_conversion():
# Large number of CSS styles for conversion
styles = [("font-weight", "bold"), ("color", "red")] * 25 # 50 styles
codeflash_output = _parse_latex_cell_styles(styles, "val", convert_css=True); result = codeflash_output # 71.7μs -> 43.0μs (66.7% faster)
# Should nest as: \bfseries{\color{red} ...{\bfseries{\color{red} val}}...}
expected = "val"
for _ in range(25):
expected = r"\bfseries{\color{red} " + expected + "}"
def test_large_scale_mixed_flags_and_conversion():
# Large number of CSS styles, alternating flags
styles = []
for i in range(25):
styles.append(("font-weight", "bold--wrap"))
styles.append(("color", f"red--rwrap"))
codeflash_output = _parse_latex_cell_styles(styles, "val", convert_css=True); result = codeflash_output # 102μs -> 96.7μs (5.61% faster)
# Should alternate nesting between --wrap and --rwrap
expected = "val"
for _ in range(25):
expected = r"{\bfseries \color{red}{%s}}" % expected
def test_large_scale_empty_display_value():
# Large number of styles, empty display value
styles = [(f"cmd{i}", f"opt{i}") for i in range(100)]
codeflash_output = _parse_latex_cell_styles(styles, "",); result = codeflash_output # 88.2μs -> 25.9μs (241% faster)
expected = ""
for i in reversed(range(100)):
expected = f"\cmd{i}opt{i}{{{expected}}}"
--------------------- DETERMINISM AND EDGE CONSISTENCY ---------------------
@pytest.mark.parametrize("styles,display_value,expected", [
([("cmd", "opt--wrap")], "val", r"{\cmdopt val}"),
([("cmd", "opt--rwrap")], "val", r"\cmdopt{val}"),
([("cmd", "opt--nowrap")], "val", r"\cmdopt val"),
([("cmd", "opt--lwrap")], "val", r"{\cmdopt} val"),
([("cmd", "opt--dwrap")], "val", r"{\cmdopt}{val}"),
([("cmd", "opt /* --wrap /")], "val", r"{\cmdopt val}"),
([("cmd", "opt--wrap / comment */")], "val", r"{\cmdopt val}"),
])
def test_parametrized_flags_and_comments(styles, display_value, expected):
# Parametrized tests for flags and comments
codeflash_output = _parse_latex_cell_styles(styles, display_value); result = codeflash_output # 30.6μs -> 34.8μs (12.0% slower)
def test_flag_with_float_option_and_comment():
# Option is float and contains comment
codeflash_output = _parse_latex_cell_styles([("fontsize", "12.5 /* --rwrap */")], "val"); result = codeflash_output # 4.76μs -> 5.18μs (8.09% slower)
def test_flag_with_whitespace_and_comment():
# Option has whitespace and comment
codeflash_output = _parse_latex_cell_styles([("cmd", "opt /* --wrap */ ")], "val"); result = codeflash_output # 4.47μs -> 5.08μs (11.8% slower)
def test_flag_with_multiple_comments_and_flags():
# Option has multiple comments and flags
codeflash_output = _parse_latex_cell_styles([("cmd", "opt /* --wrap / / other */ --rwrap")], "val"); result = codeflash_output # 4.86μs -> 5.46μs (11.0% slower)
def test_convert_css_with_percent_rgb():
# CSS rgb with percent values
codeflash_output = _parse_latex_cell_styles([("color", "rgb(50%, 100%, 0%)")], "val", convert_css=True); result = codeflash_output # 19.2μs -> 17.4μs (9.87% faster)
def test_convert_css_with_percent_rgba():
# CSS rgba with percent values
codeflash_output = _parse_latex_cell_styles([("color", "rgba(50%, 100%, 0%, 0.5)")], "val", convert_css=True); result = codeflash_output # 16.9μs -> 16.1μs (5.50% faster)
def test_convert_css_with_multiple_flags_in_value():
# CSS conversion, value contains multiple flags
codeflash_output = _parse_latex_cell_styles([("font-weight", "bold--wrap--rwrap")], "val", convert_css=True); result = codeflash_output # 5.39μs -> 6.85μs (21.4% slower)
def test_convert_css_with_flag_and_comment():
# CSS conversion, value contains flag and comment
codeflash_output = _parse_latex_cell_styles([("font-weight", "bold /* --wrap */")], "val", convert_css=True); result = codeflash_output # 8.60μs -> 11.1μs (22.6% slower)
def test_convert_css_with_flag_and_extra_whitespace():
# CSS conversion, value contains flag and extra whitespace
codeflash_output = _parse_latex_cell_styles([("font-weight", "bold --wrap ")], "val", convert_css=True); result = codeflash_output # 8.19μs -> 10.4μs (21.0% slower)
def test_convert_css_with_flag_and_multiple_comments():
# CSS conversion, value contains flag and multiple comments
codeflash_output = _parse_latex_cell_styles([("font-weight", "bold /* --wrap / / extra */")], "val", convert_css=True); result = codeflash_output # 5.80μs -> 7.54μs (23.2% slower)
codeflash_output is used to check that the output of the original code is the same as that of the optimized code.
To edit these changes
git checkout codeflash/optimize-_parse_latex_cell_styles-mhvn66j5and push.